namespace ClassyBlog.DomainObjects
{
    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Dynamic;
    using System.Linq.Expressions;

    using Infrastructure;

    public class Post : IArticle
    {
        private readonly ICollection<Tag> tags;
        private Guid id;
        private bool allowComments;

        [DebuggerStepThrough]
        public Post()
        {
            tags = new List<Tag>();
            id = Guid.NewGuid();
            allowComments = true;
            DynamicProperties = new Dictionary<string, object>();
        }

        public virtual Guid Id
        {
            [DebuggerStepThrough]
            get { return id; }

            [DebuggerStepThrough]
            set { id = value; }
        }

        public virtual DateTime PublishedAt { get; set; }

        public virtual string Slug { get; set; }

        public virtual string Type { get; set; }

        public virtual string Title { get; set; }

        public virtual string MetaKeywords { get; set; }

        public virtual string MetaDescription { get; set; }

        public virtual string Author { get; set; }

        public virtual bool AllowComments
        {
            [DebuggerStepThrough]
            get { return allowComments; }

            [DebuggerStepThrough]
            set { allowComments = value; }
        }

        public virtual ICollection<Tag> Tags
        {
            [DebuggerStepThrough]
            get { return tags; }
        }

        public virtual string Body { get; set; }

        public virtual IEnumerable<string> DynamicPropertyNames
        {
            [DebuggerStepThrough]
            get { return DynamicProperties.Keys; }
        }

        protected IDictionary<string, object> DynamicProperties { get; private set; }

        public virtual DynamicMetaObject GetMetaObject(Expression parameter)
        {
            return new DynamicPropertiesMetaObject(parameter, this);
        }

        public virtual object GetDynamicProperty(string name)
        {
            object value;

            return DynamicProperties.TryGetValue(name, out value) ?
                   value :
                   null;
        }

        public virtual void SetDynamicProperty(string name, object value)
        {
            DynamicProperties[name] = value;
        }
    }
}